// Copyright (C) 2020-2022 Intel Corporation
// Copyright (C) 2024 CVAT.ai Corporation
//
// SPDX-License-Identifier: MIT

import React from 'react';
import { Row, Col } from 'antd/lib/grid';
import Icon, {
    TeamOutlined,
    UserOutlined,
    PushpinFilled,
    PushpinOutlined,
    StarFilled,
    SelectOutlined,
    StarOutlined,
} from '@ant-design/icons';

import CVATTooltip from 'components/common/cvat-tooltip';
import { CombinedState, ObjectType, ShapeType } from 'reducers';
import {
    ObjectOutsideIcon,
    FirstIcon,
    LastIcon,
    PreviousIcon,
    NextIcon,
    DeleteIcon,
    CopyAttributeIcon,
    EyeCloseIcon,
    EyeIcon,
    LockIcon,
    UnlockIcon,
    EditIcon,
} from 'icons';
import { Button, Popconfirm } from 'antd';
import { useDispatch, useSelector } from 'react-redux';
import {
    editFirstReview,
    editSecondReview,
    toggleFirstReviewDetail,
    toggleSecondReviewDetail,
} from 'actions/annotation-actions';
import ObjectState from 'cvat-core/src/object-state';
import { cloneDeep } from 'lodash';
import useAnnotation from 'hooks/useAnnotation';
import { JobStatusEnum } from 'typings/annotion/task';
import { useParams } from 'react-router-dom-v5-compat';

interface Props {
    readonly: boolean;
    parentID: number | null;
    clientID: number | null;
    objectType: ObjectType;
    shapeType: ShapeType;
    occluded: boolean;
    outside: boolean | undefined;
    locked: boolean;
    pinned: boolean;
    hidden: boolean;
    keyframe: boolean | undefined;
    isCopyActive: boolean;
    outsideDisabled: boolean;
    hiddenDisabled: boolean;
    keyframeDisabled: boolean;
    switchOccludedShortcut: string;
    switchPinnedShortcut: string;
    switchOutsideShortcut: string;
    switchLockShortcut: string;
    switchHiddenShortcut: string;
    switchKeyFrameShortcut: string;
    nextKeyFrameShortcut: string;
    prevKeyFrameShortcut: string;

    navigateFirstKeyframe: null | (() => void);
    navigatePrevKeyframe: null | (() => void);
    navigateNextKeyframe: null | (() => void);
    navigateLastKeyframe: null | (() => void);

    setOccluded(): void;
    unsetOccluded(): void;
    setOutside(): void;
    unsetOutside(): void;
    setKeyframe(): void;
    unsetKeyframe(): void;
    lock(): void;
    unlock(): void;
    pin(): void;
    unpin(): void;
    hide(): void;
    show(): void;
    remove(): void;
    toggleCopy(): void;
}

const classes = {
    firstKeyFrame: { className: 'cvat-object-item-button-first-keyframe' },
    prevKeyFrame: { className: 'cvat-object-item-button-prev-keyframe' },
    nextKeyFrame: { className: 'cvat-object-item-button-next-keyframe' },
    lastKeyFrame: { className: 'cvat-object-item-button-last-keyframe' },
    outside: {
        enabled: { className: 'cvat-object-item-button-outside cvat-object-item-button-outside-enabled' },
        disabled: { className: 'cvat-object-item-button-outside' },
    },
    lock: {
        enabled: { className: 'cvat-object-item-button-lock cvat-object-item-button-lock-enabled' },
        disabled: { className: 'cvat-object-item-button-lock' },
    },
    occluded: {
        enabled: { className: 'cvat-object-item-button-occluded cvat-object-item-button-occluded-enabled' },
        disabled: { className: 'cvat-object-item-button-occluded' },
    },
    pinned: {
        enabled: { className: 'cvat-object-item-button-pinned cvat-object-item-button-pinned-enabled' },
        disabled: { className: 'cvat-object-item-button-pinned' },
    },
    hidden: {
        enabled: { className: 'cvat-object-item-button-hidden cvat-object-item-button-hidden-enabled' },
        disabled: { className: 'cvat-object-item-button-hidden' },
    },
    keyframe: {
        enabled: { className: 'cvat-object-item-button-keyframe cvat-object-item-button-keyframe-enabled' },
        disabled: { className: 'cvat-object-item-button-keyframe' },
    },
};

function NavigateFirstKeyframe(props: Props): JSX.Element {
    const { navigateFirstKeyframe } = props;
    return navigateFirstKeyframe ? (
        <Icon {...classes.firstKeyFrame} component={FirstIcon} onClick={navigateFirstKeyframe} />
    ) : (
        <Icon {...classes.firstKeyFrame} component={FirstIcon} style={{ opacity: 0.5, pointerEvents: 'none' }} />
    );
}

function NavigatePrevKeyframe(props: Props): JSX.Element {
    const { prevKeyFrameShortcut, navigatePrevKeyframe } = props;
    return navigatePrevKeyframe ? (
        <CVATTooltip title={`Go to previous keyframe ${prevKeyFrameShortcut}`}>
            <Icon {...classes.prevKeyFrame} component={PreviousIcon} onClick={navigatePrevKeyframe} />
        </CVATTooltip>
    ) : (
        <Icon {...classes.prevKeyFrame} component={PreviousIcon} style={{ opacity: 0.5, pointerEvents: 'none' }} />
    );
}

function NavigateNextKeyframe(props: Props): JSX.Element {
    const { navigateNextKeyframe, nextKeyFrameShortcut } = props;
    return navigateNextKeyframe ? (
        <CVATTooltip title={`Go to next keyframe ${nextKeyFrameShortcut}`}>
            <Icon {...classes.nextKeyFrame} component={NextIcon} onClick={navigateNextKeyframe} />
        </CVATTooltip>
    ) : (
        <Icon {...classes.nextKeyFrame} component={NextIcon} style={{ opacity: 0.5, pointerEvents: 'none' }} />
    );
}

function NavigateLastKeyframe(props: Props): JSX.Element {
    const { navigateLastKeyframe } = props;
    return navigateLastKeyframe ? (
        <Icon {...classes.lastKeyFrame} component={LastIcon} onClick={navigateLastKeyframe} />
    ) : (
        <Icon {...classes.lastKeyFrame} component={LastIcon} style={{ opacity: 0.5, pointerEvents: 'none' }} />
    );
}

function SwitchLock(props: Props): JSX.Element {
    const { locked, switchLockShortcut, lock, unlock } = props;
    return (
        <CVATTooltip title={`Switch lock property ${switchLockShortcut}`}>
            {locked ? (
                <Icon {...classes.lock.enabled} component={LockIcon} onClick={unlock} className='!text-20px' />
            ) : (
                <Icon {...classes.lock.disabled} component={UnlockIcon} onClick={lock} className='!text-20px' />
            )}
        </CVATTooltip>
    );
}

function SwitchOccluded(props: Props): JSX.Element {
    const { switchOccludedShortcut, occluded, unsetOccluded, setOccluded } = props;
    return (
        <CVATTooltip title={`Switch occluded property ${switchOccludedShortcut}`}>
            {occluded ? (
                <TeamOutlined {...classes.occluded.enabled} onClick={unsetOccluded} />
            ) : (
                <UserOutlined {...classes.occluded.disabled} onClick={setOccluded} />
            )}
        </CVATTooltip>
    );
}

function SwitchPinned(props: Props): JSX.Element {
    const { switchPinnedShortcut, pinned, pin, unpin } = props;
    return (
        <CVATTooltip title={`Switch pinned property ${switchPinnedShortcut}`}>
            {pinned ? (
                <PushpinFilled {...classes.pinned.enabled} onClick={unpin} />
            ) : (
                <PushpinOutlined {...classes.pinned.disabled} onClick={pin} />
            )}
        </CVATTooltip>
    );
}

/**
 * 显示/隐藏
 */
function SwitchHidden(props: Props): JSX.Element {
    const { switchHiddenShortcut, hidden, hiddenDisabled, show, hide } = props;
    const hiddenStyle = hiddenDisabled ? { opacity: 0.5, pointerEvents: 'none' as const } : {};
    return (
        <CVATTooltip title={`Switch hidden property ${switchHiddenShortcut}`}>
            {hidden ? (
                <Icon
                    {...classes.hidden.enabled}
                    component={EyeCloseIcon}
                    onClick={show}
                    style={hiddenStyle}
                    className='!text-20px'
                />
            ) : (
                <Icon
                    {...classes.hidden.disabled}
                    component={EyeIcon}
                    onClick={hide}
                    style={hiddenStyle}
                    className='!text-20px'
                />
            )}
        </CVATTooltip>
    );
}

function SwitchOutside(props: Props): JSX.Element {
    const { outside, switchOutsideShortcut, outsideDisabled, unsetOutside, setOutside } = props;
    const outsideStyle = outsideDisabled ? { opacity: 0.5, pointerEvents: 'none' as const } : {};
    return (
        <CVATTooltip title={`Switch outside property ${switchOutsideShortcut}`}>
            {outside ? (
                <Icon
                    {...classes.outside.enabled}
                    component={ObjectOutsideIcon}
                    onClick={unsetOutside}
                    style={outsideStyle}
                />
            ) : (
                <SelectOutlined {...classes.outside.disabled} onClick={setOutside} style={outsideStyle} />
            )}
        </CVATTooltip>
    );
}

function SwitchKeyframe(props: Props): JSX.Element {
    const { keyframe, switchKeyFrameShortcut, keyframeDisabled, unsetKeyframe, setKeyframe } = props;
    const keyframeStyle = keyframeDisabled ? { opacity: 0.5, pointerEvents: 'none' as const } : {};
    return (
        <CVATTooltip title={`Switch keyframe property ${switchKeyFrameShortcut}`}>
            {keyframe ? (
                <StarFilled style={keyframeStyle} onClick={unsetKeyframe} {...classes.keyframe.enabled} />
            ) : (
                <StarOutlined style={keyframeStyle} onClick={setKeyframe} {...classes.keyframe.disabled} />
            )}
        </CVATTooltip>
    );
}

/**
 * 复制标签及属性
 */
function SwitchCopyAttribute(props: Props): JSX.Element {
    const { toggleCopy, isCopyActive } = props;
    return (
        <CVATTooltip title='Copy attributes'>
            <span className={isCopyActive ? ' p-6px bg-[#F7F8FA] rounded-2px' : 'p-6px'}>
                <Icon
                    component={CopyAttributeIcon}
                    onClick={toggleCopy}
                    className={isCopyActive ? '!text-[#165DFF]' : ''}
                />
            </span>
        </CVATTooltip>
    );
}

function ItemButtonsComponent(props: Props): JSX.Element {
    const { readonly, objectType, shapeType, clientID, remove } = props;
    const dispatch = useDispatch();
    const params = useParams();
    const annotationData = useSelector((state: CombinedState) => state.annotation.approval.annotationData);
    const { jobStatus } = useAnnotation();
    const [, firstReview = {}, secondReview = {}] = annotationData?.[clientID!] || [];
    const approvalStatus = firstReview?.approvalStatus;
    const secondApprovalStatus = secondReview?.approvalStatus;

    if (objectType === ObjectType.TRACK) {
        return (
            <Row align='middle' justify='space-around'>
                <Col span={20} style={{ textAlign: 'center' }}>
                    <Row justify='space-around'>
                        <Col>
                            <NavigateFirstKeyframe {...props} />
                        </Col>
                        <Col>
                            <NavigatePrevKeyframe {...props} />
                        </Col>
                        <Col>
                            <NavigateNextKeyframe {...props} />
                        </Col>
                        <Col>
                            <NavigateLastKeyframe {...props} />
                        </Col>
                    </Row>
                    {readonly ? (
                        <Row justify='space-around'>
                            <Col>
                                <SwitchHidden {...props} />
                            </Col>
                        </Row>
                    ) : (
                        <Row justify='space-around'>
                            <Col>
                                <SwitchOutside {...props} />
                            </Col>
                            <Col>
                                <SwitchLock {...props} />
                            </Col>
                            <Col>
                                <SwitchOccluded {...props} />
                            </Col>
                            <Col>
                                <SwitchHidden {...props} />
                            </Col>
                            <Col>
                                <SwitchKeyframe {...props} />
                            </Col>
                            {shapeType !== ShapeType.POINTS && (
                                <Col>
                                    <SwitchPinned {...props} />
                                </Col>
                            )}
                        </Row>
                    )}
                </Col>
            </Row>
        );
    }

    /**
     * 初审修改数据
     */
    const handleFirstReviewEdit = () => {
        const activatedData = cloneDeep(annotationData[clientID as unknown as any]);
        dispatch(editFirstReview(clientID!, activatedData));
    };
    /**
     * 复审修改数据
     */
    const handleSecondReviewEdit = () => {
        const activatedData = cloneDeep(annotationData[clientID as unknown as any]);
        dispatch(editSecondReview(clientID!, activatedData));
    };

    // 查看初审修改数据
    const firstReviewDetail = () => {
        const activatedData = cloneDeep(annotationData[clientID as unknown as any]);
        dispatch(toggleFirstReviewDetail(clientID!, activatedData));
    };
    // 查看复审修改数据
    const secondReviewDetail = () => {
        const activatedData = cloneDeep(annotationData[clientID as unknown as any]);
        dispatch(toggleSecondReviewDetail(clientID!, activatedData));
    };

    // 查看
    if (params.action === 'view') {
        const showView =
            [JobStatusEnum.WAITING_FIRST_REVIEW, JobStatusEnum.SECOND_REVIEW_REJECTED].includes(jobStatus) &&
            approvalStatus === 1;
        const showSecondView =
            jobStatus === JobStatusEnum.WAITING_SECOND_REVIEW &&
            !!secondApprovalStatus &&
            secondReview.correctIndex === 2;
        return (
            <div className='flex justify-between items-center'>
                <SwitchHidden {...props} />
                {/* 初审查看 */}
                {showView && (
                    <Button type='primary' ghost autoInsertSpace={false} onClick={firstReviewDetail}>
                        查看
                    </Button>
                )}
                {/* 复审查看 */}
                {showSecondView && (
                    <Button type='primary' ghost autoInsertSpace={false} onClick={secondReviewDetail}>
                        查看
                    </Button>
                )}
            </div>
        );
    }

    if (objectType === ObjectType.SHAPE) {
        return (
            <Row align='middle' justify='space-around'>
                <Col span={24} style={{ textAlign: 'center' }}>
                    {[JobStatusEnum.WAITING_ANNOTATION, JobStatusEnum.FIRST_REVIEW_REJECTED].includes(jobStatus) ? (
                        <Row>
                            <Col>
                                <SwitchLock {...props} />
                            </Col>
                            <div className='flex justify-evenly flex-1'>
                                <Col>
                                    <SwitchHidden {...props} />
                                </Col>
                                <Col>
                                    <SwitchCopyAttribute {...props} />
                                </Col>
                            </div>
                            <Col>
                                <Popconfirm
                                    title='提示'
                                    description='确认删除该标注?'
                                    onConfirm={remove}
                                    okText='确定'
                                    cancelText='取消'
                                >
                                    <Icon component={DeleteIcon} />
                                </Popconfirm>
                            </Col>
                        </Row>
                    ) : (
                        <div className='flex justify-between items-center'>
                            <div className='flex gap-3'>
                                <SwitchLock {...props} />
                                <SwitchHidden {...props} />
                            </div>
                            {params.action === 'review' && (
                                <>
                                    {/* 初审 */}
                                    {[
                                        JobStatusEnum.WAITING_FIRST_REVIEW,
                                        JobStatusEnum.SECOND_REVIEW_REJECTED,
                                    ].includes(jobStatus) && (
                                        <Button
                                            type='primary'
                                            ghost
                                            autoInsertSpace={false}
                                            onClick={handleFirstReviewEdit}
                                        >
                                            {approvalStatus !== 1 && <Icon component={EditIcon} />}
                                            {approvalStatus === 1 ? '查看' : '修改'}
                                        </Button>
                                    )}
                                    {/* 复审，点击纠正 */}
                                    {jobStatus === JobStatusEnum.WAITING_SECOND_REVIEW &&
                                        !!secondApprovalStatus &&
                                        [undefined, 2].includes(secondReview.correctIndex) && (
                                            <Button
                                                type='primary'
                                                ghost
                                                autoInsertSpace={false}
                                                onClick={handleSecondReviewEdit}
                                            >
                                                {secondApprovalStatus === 1 && <Icon component={EditIcon} />}
                                                <span>{secondApprovalStatus === 1 ? '纠正' : '查看'}</span>
                                            </Button>
                                        )}
                                </>
                            )}
                        </div>
                    )}
                </Col>
            </Row>
        );
    }

    if (readonly) {
        return <div />;
    }

    return (
        <Row align='middle' justify='space-around'>
            <Col span={20} style={{ textAlign: 'center' }}>
                <Row justify='space-around'>
                    <Col>
                        <SwitchLock {...props} />
                    </Col>
                </Row>
            </Col>
        </Row>
    );
}

export default React.memo(ItemButtonsComponent);
